import jwt
import datetime
from flask import Blueprint, request, jsonify, current_app
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
from app.extensions import db
from app.models import User
from routes.user import verify_password

# 创建认证蓝图（统一前缀：/api/v1）
auth_bp = Blueprint('auth', __name__, url_prefix='/api/v1')

# 初始化limiter
limiter = Limiter(
    app=current_app,
    key_func=get_remote_address,
    default_limits=["200 per day", "50 per hour"],
    storage_uri="memory://"
)

# 生成 JWT 令牌
def generate_token(user_id):
    """生成包含用户ID的JWT令牌，有效期2小时"""
    payload = {
        'exp': datetime.datetime.utcnow() + datetime.timedelta(hours=2),  # 过期时间
        'iat': datetime.datetime.utcnow(),  # 签发时间
        'sub': str(user_id)  # 主题（存储用户ID）
    }
    # 使用密钥签名令牌
    token = jwt.encode(payload, current_app.config['SECRET_KEY'], algorithm='HS256')
    return token


# 验证 JWT 令牌（装饰器，用于保护需要登录的接口）
def token_required(f):
    from functools import wraps
    @wraps(f)
    def decorated(*args, **kwargs):
        # token = None
        # 从请求头获取令牌（格式：Authorization: Bearer <token>）
        auth_header = request.headers.get('Authorization')
        if auth_header and auth_header.startswith('Bearer '):
            token = auth_header.split(' ')[1]
        

        if not token:
            return jsonify({
                "code": 401,
                "message": "认证失败",
                "errors": {"general": "请提供令牌"}
            }), 401

        try:
            # 验证令牌并解析 payload
            payload = jwt.decode(
                token,
                current_app.config['SECRET_KEY'],
                algorithms=['HS256']
            )
            current_user_id = payload['sub']
            # 从数据库获取用户（可选：验证用户是否存在）
            current_user = User.query.get(current_user_id)
            if not current_user:
                raise Exception("用户不存在")
        except jwt.ExpiredSignatureError:
            return jsonify({
                "code": 401,
                "message": "认证失败",
                "errors": {"general": "令牌已过期"}
            }), 401
        except Exception as e:
            return jsonify({
                "code": 401,
                "message": "认证失败",
                "errors": {"general": str(e)}
            }), 401

        # 将用户ID传递给视图函数
        return f(current_user_id, *args, **kwargs)

    return decorated


# 登录接口（获取JWT令牌）
@auth_bp.route('/login', methods=['POST'])
@limiter.limit("10 per minute")
def login():
    data = request.get_json()
    if not data:
        return jsonify({
            "code": 400,
            "message": "登录失败",
            "errors": {"general": "请提供JSON数据"}
        }), 400

    username = data.get('username', '').strip()
    password = data.get('password', '').strip()
    errors = {}

    if not username:
        errors['username'] = "用户名不能为空"
    if not password:
        errors['password'] = "密码不能为空"
    if errors:
        return jsonify({
            "code": 400,
            "message": "登录失败",
            "errors": errors
        }), 400

    # 验证用户
    user = User.query.filter_by(username=username).first()
    if not user:
        return jsonify({
            "code": 401,
            "message": "登录失败",
            "errors": {"general": "用户名或密码错误"}
        }), 401

    # 验证密码（使用user.py中的verify_password函数）
    if not verify_password(user.password_hash, password):
        return jsonify({
            "code": 401,
            "message": "登录失败",
            "errors": {"general": "用户名或密码错误"}
        }), 401

    # 生成令牌
    token = generate_token(user.id)
    return jsonify({
        "code": 200,
        "message": "登录成功",
        "data": {
            "token": token,
            "username": user.username,
            "expires_in": 7200  # 令牌有效期（秒）
        }
    }), 200


# 注销接口（JWT无需服务器存储，客户端删除令牌即可，这里仅作为示例）
@auth_bp.route('/logout', methods=['POST'])
@token_required  # 需要登录才能访问
def logout(current_user_id):
    # JWT是无状态的，注销只需客户端丢弃令牌，服务器无需处理
    return jsonify({
        "code": 200,
        "message": "注销成功"
    }), 200


# 示例：需要登录的接口（使用token_required装饰器保护）
@auth_bp.route('/profile', methods=['GET'])
@token_required
def get_profile(current_user_id):
    user = User.query.get(current_user_id)
    return jsonify({
        "code": 200,
        "data": {
            "username": user.username,
            "created_at": user.created_at.strftime("%Y-%m-%d %H:%M:%S")
        }
    }), 200